﻿using System;
using System.Linq.Expressions;
using AutoMapper;
using CarAppDomain.Sys.Entities;
using CarAppDomain.Sys.IRepositories;
using CarAppDto.Sys.AdminDtos;
using CarAppService.Sys.IServices;
using D.Util.UtilCache;
using D.Util.UtilConfiguration;
using D.UtilCore.Dtos;
using D.UtilCore.JwtUtil;
using D.UtilCore.Models;
using D.UtilCore.Utils;
using D.UtilSqlsugarOrm;
using Microsoft.AspNetCore.Http;

namespace CarAppDomain.Sys.Services
{
    /// <summary>
    /// 管理员业务实现
    /// </summary>
    public class AdminService : BaseService<SysAdminEntity>, IAdminService
    {
        private readonly IMapper _mapper;
        private readonly ICacheService _cache;
        private readonly IJwtService _tokenService;
        private readonly ISysAdminEntityRepository _repository;
        private readonly IHttpContextAccessor _httpContextAccessor;

        /// <summary>
        /// 构造注入
        /// </summary>
        public AdminService(IMapper mapper, ICacheService cache, IJwtService tokenService, IHttpContextAccessor httpContextAccessor, ISysAdminEntityRepository repository)
        {
            // 用于base方法
            base._baseDal = repository;
            this._repository = repository;
            _cache = cache;
            _mapper = mapper;
            _tokenService = tokenService;
            _httpContextAccessor = httpContextAccessor;
        }

        #region 增删改查


        /// <summary>
        /// 新增用户
        /// </summary>
        /// <param name="reqModel"></param>
        /// <returns></returns>
        public async Task<ApiResult<int>> AddAdminAsync(ReqAddAdmin reqModel)
        {
            var exists = await _repository.ExistsAsync(m => m.Account == reqModel.Account);
            if (exists)
            {
                return new ApiResult<int>() { Code = StatusCodeEnum.Waring, ErrorMsg = "账号已存在" };
            }
            var insertEntity = _mapper.Map<ReqAddAdmin, SysAdminEntity>(reqModel);
            insertEntity.DeleteFlag = false;
            insertEntity.CreateTime = DateTime.Now;
            insertEntity.Id = Guid.NewGuid().ToString();
            insertEntity.LoginTotalCount = 0;
            var dbres = await _repository.AddAsync(insertEntity);
            return dbres.NormalResponse();
        }

        /// <summary>
        /// 删除用户
        /// </summary>
        /// <param name="ids"></param>
        /// <returns></returns>
        public async Task<ApiResult<int>> DeleteAdminAsync(List<string> ids)
        {
            var dbres = await _repository.DeleteAsync(m => ids.Contains(m.Id));
            return dbres.NormalResponse();
        }

        /// <summary>
        /// 修改用户
        /// </summary>
        /// <param name="reqModel"></param>
        /// <returns></returns>
        public async Task<ApiResult<int>> UpdateAdminAsync(ReqUpdateAdmin reqModel)
        {
            var updateEntity = await _repository.GetModelAsync(m => m.Id == reqModel.Id);
            if (updateEntity == null)
            {
                return new ApiResult<int>() { Code = StatusCodeEnum.Waring, ErrorMsg = "该信息不存在" };
            }

            updateEntity.Status = reqModel.Status;
            updateEntity.Email = reqModel.Email;
            updateEntity.NickName = reqModel.NickName;
            updateEntity.UUID = reqModel.UUID;
            updateEntity.UpdateTime = DateTime.Now;
            updateEntity.UpdateUser = reqModel.UpdateUser;

            var dbres = await _repository.UpdateAsync(updateEntity);
            return dbres.NormalResponse();
        }

        /// <summary>
        /// 获取用户详情
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<ApiResult<RepAdminInfo>> GetAdminAsync(string id)
        {
            var dbres = await _repository.GetModelAsync(m => m.Id == id);
            var res = _mapper.Map<SysAdminEntity, RepAdminInfo>(dbres);
            return res.GetResponse();
        }

        /// <summary>
        /// 获取用户列表
        /// </summary>
        /// <param name="reqGueryAdminList"></param>
        /// <returns></returns>
        public async Task<ApiResult<List<RepAdminInfo>>> QueryAdminListAsync(ReqGueryAdminList reqGueryAdminList)
        {

            Expression<Func<SysAdminEntity, bool>> where = null;
            if (!string.IsNullOrEmpty(reqGueryAdminList.Account))
            {
                where = where.And(m => m.Account.Contains(reqGueryAdminList.Account));
            }
            if (!string.IsNullOrEmpty(reqGueryAdminList.NickName))
            {
                where = where.And(where => where.NickName.Contains(reqGueryAdminList.NickName));
            }

            if (!string.IsNullOrEmpty(reqGueryAdminList.UUID))
            {
                where = where.And(where => where.UUID.Contains(reqGueryAdminList.UUID));
            }

            if (reqGueryAdminList.Status != null)
            {
                where = where.And(where => where.Status == reqGueryAdminList.Status);
            }

            var dbres = await _repository.GetListAsync(where);
            var res = _mapper.Map<List<SysAdminEntity>, List<RepAdminInfo>>(dbres);
            return res.GetResponse();
        }
        /// <summary>
        /// 获取用户分页
        /// </summary>
        /// <param name="reqQueryAdminPage"></param>
        /// <returns></returns>
        public async Task<ApiResult<PageModel<RepAdminInfo>>> QueryAdminPagesAsync(ReqQueryAdminPage reqQueryAdminPage)
        {
            Expression<Func<SysAdminEntity, bool>> where = null;
            if (!string.IsNullOrEmpty(reqQueryAdminPage.Account))
            {
                where = where.And(m => m.Account.Contains(reqQueryAdminPage.Account));
            }

            if (!string.IsNullOrEmpty(reqQueryAdminPage.NickName))
            {
                where = where.And(m => m.NickName.Contains(reqQueryAdminPage.NickName));
            }

            if (!string.IsNullOrEmpty(reqQueryAdminPage.UUID))
            {
                where = where.And(m => m.UUID.Contains(reqQueryAdminPage.UUID));
            }

            if (reqQueryAdminPage.Status != null)
            {
                where = where.And(m => m.Status == reqQueryAdminPage.Status);
            }

            var dbres = await _repository.GetPagesAsync(reqQueryAdminPage.PageSize, reqQueryAdminPage.PageNo, where, m => m.CreateTime);
            var res = new PageModel<RepAdminInfo>()
            {
                PageNo = dbres.PageNo,
                PageSize = dbres.PageSize,
                TotalCount = dbres.TotalCount,
                TotalPage = dbres.TotalPage,
                Data = _mapper.Map<List<SysAdminEntity>, List<RepAdminInfo>>(dbres.Data)
            };
            return res.GetResponse();
        }
        #endregion

        #region 登录

        /// <summary>
        /// 登录
        /// </summary>
        /// <param name="account"></param>
        /// <param name="pwd"></param>
        /// <param name="ip"></param>
        /// <returns></returns>
        public async Task<ApiResult<string>> LoginAsync(string account, string pwd)
        {
            var res = new ApiResult<string>()
            {
                Code = StatusCodeEnum.Waring
            };

            #region 1. 判断用户登录次数限制以及过期时间

            //获得登录次数和过期时间
            var loginConfig = _cache.Get<CacheAdminLogin>(CacheKey.LoginCount + "-" + account) ?? new CacheAdminLogin();
            if (loginConfig.Account == account && loginConfig.Count == 4 && loginConfig.DelayMinute != null)
            {
                //说明存在过期时间，需要判断
                if (DateTime.Now <= loginConfig.DelayMinute)
                {
                    res.ErrorMsg = "您已连续登录失败超过3次，请稍后3分钟后再试";
                    return res;
                }
                else
                {
                    //已经过了登录的预设时间，重置登录配置参数 
                    loginConfig.Account = account;
                    loginConfig.Count = 0;
                    loginConfig.DelayMinute = null;
                }
            }
            #endregion

            #region 2.验证用户信息 

            var model = await _repository.GetModelAsync(m => m.Account == account && m.Pwd == pwd);
            if (model == null)
            {
                loginConfig.Count++;
                loginConfig.DelayMinute = DateTime.Now.AddMinutes(3);
                _cache.Set(CacheKey.LoginCount + "-" + account, loginConfig);

                res.ErrorMsg = "账户或密码错误";
                return res;
            }
            if (!model.Status.Value)
            {
                res.ErrorMsg = "账号已被禁用";
                return res;
            }
            #endregion

            #region 4. 生成token信息，并且返回给前端

            var _appConfig = AppsettingsUtils.Get<AppConfig>();

            var token = _tokenService.IssueToken(new TokenModel()
            {
                Id = model.Id,
                NickName = model.NickName,
                Account = model.Account,
                RoleId = model.RoleId,
                ProjectName = "CarAppAPI",
                Issuer = _appConfig.JwtConfig.Issuer,
                Audience = _appConfig.JwtConfig.Audience,
                Expires = _appConfig.JwtConfig.Expires,
                SecretKey = _appConfig.JwtConfig.SecurityKey
            });

            //清楚缓存
            _cache.Del(CacheKey.LoginCount);

            #endregion

            #region 5. 修改用户登录信息

            model.LoginTotalCount += 1;
            model.LastLoginIp = _httpContextAccessor.HttpContext.Connection.RemoteIpAddress.MapToIPv4().ToString();
            model.LastLoginTime = DateTime.Now;
            await _repository.UpdateAsync(model);

            #endregion

            res.Data = token;
            res.IsSuccess = true;
            res.Code = StatusCodeEnum.OK;

            return res;
        }

        /// <summary>
        /// 刷新token
        /// </summary>
        /// <param name="token"></param>
        /// <returns></returns>
        /// <exception cref="NotImplementedException"></exception>
        public async Task<ApiResult<string>> RefreshTokenAsync(string token)
        {
            string jwtStr = string.Empty;

            if (string.IsNullOrEmpty(token))
            {
                return new ApiResult<string>()
                {
                    IsSuccess = false,
                    ErrorMsg = "token无效，请重新登录！",
                };
            }
            var tokenModel = _tokenService.SerializeToken(token);
            if (tokenModel != null && !string.IsNullOrEmpty(tokenModel.Id))
            {
                var admin = await _repository.GetModelAsync(m => m.Id == tokenModel.Id);
                if (admin != null)
                {
                    var refreshToken = _tokenService.IssueToken(tokenModel);
                    return new ApiResult<string>()
                    {
                        IsSuccess = true,
                        ErrorMsg = "获取成功",
                        Data = refreshToken
                    };
                }
            }

            return new ApiResult<string>()
            {
                IsSuccess = false,
                ErrorMsg = "认证失败！",
            };
        }

        #endregion
    }
}
